﻿using System;
using System.Collections.Generic;
using System.IO.Ports;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ModubsRTUTempactureCurve.Base
{
    public class SerialPortService : IDisposable
    {
        private SerialPort _serialPort;
        private readonly SemaphoreSlim _serialLock = new SemaphoreSlim(1, 1);
        private bool _disposed = false;

        public event Action<string> MessageReceived;
        public event Action<string, bool> ErrorOccurred;
        public event Action<string> StatusChanged;

        // 获取所有可用的COM口
        public static string[] GetAvailablePorts()
        {
            try
            {
                return SerialPort.GetPortNames().OrderBy(p => p).ToArray();
            }
            catch (Exception)
            {
                return new string[0];
            }
        }

        // 测试COM口是否可用
        public async Task<bool> TestPortAsync(string portName, int baudRate = 9600)
        {
            if (_disposed) return false;

            await _serialLock.WaitAsync();
            try
            {
                using var testPort = new SerialPort
                {
                    PortName = portName,
                    BaudRate = baudRate,
                    Parity = Parity.None,
                    StopBits = StopBits.One,
                    WriteTimeout = 2000,
                    ReadTimeout = 3000
                };

                return await Task.Run(() =>
                {
                    try
                    {
                        testPort.Open();
                        // 简单的测试命令
                        byte[] testCmd = new byte[8];
                        testCmd[0] = (byte)0x01;
                        testCmd[1] = 0x03;
                        testCmd[2] = 0x00;
                        testCmd[3] = 0x00;
                        testCmd[4] = 0x00;
                        testCmd[5] = 0x02;
                        CRC16(testCmd);

                        testPort.Write(testCmd, 0, testCmd.Length);
                        Thread.Sleep(100);

                        return testPort.BytesToRead > 0;
                    }
                    catch
                    {
                        return false;
                    }
                    finally
                    {
                        if (testPort.IsOpen)
                            testPort.Close();
                    }
                });
            }
            finally
            {
                _serialLock.Release();
            }
        }

        // 切换到新的COM口
        public async Task<bool> SwitchPortAsync(string newPortName, int newBaudRate)
        {
            if (_disposed) return false;

            await _serialLock.WaitAsync();
            try
            {
                // 关闭当前串口
                SafeCloseSerialPort();

                // 创建新的串口实例
                _serialPort = new SerialPort
                {
                    PortName = newPortName,
                    BaudRate = newBaudRate,
                    Parity = Parity.None,
                    StopBits = StopBits.One,
                    WriteTimeout = 2000,
                    ReadTimeout = 3000
                };

                // 尝试打开新串口
                return await OpenSerialAsync();
            }
            finally
            {
                _serialLock.Release();
            }
        }

        private async Task<bool> OpenSerialAsync()
        {
            return await Task.Run(() =>
            {
                try
                {
                    _serialPort.Open();
                    StatusChanged?.Invoke($"已连接到 {_serialPort.PortName}");
                    return true;
                }
                catch (Exception ex)
                {
                    ErrorOccurred?.Invoke($"无法打开 {_serialPort.PortName}: {ex.Message}", false);
                    return false;
                }
            });
        }

        private void SafeCloseSerialPort()
        {
            try
            {
                if (_serialPort?.IsOpen == true)
                {
                    _serialPort.Close();
                    StatusChanged?.Invoke("串口已关闭");
                }
            }
            catch (Exception ex)
            {
                ErrorOccurred?.Invoke($"关闭串口时出错: {ex.Message}", false);
            }
        }

        private void CRC16(byte[] value)
        {
            if (value == null || !value.Any())
                throw new ArgumentException("Value cannot be null or empty.");

            // 运算
            ushort crc = 0xFFFF;
            for (int i = 0; i < value.Length - 2; i++)
            {
                crc = (ushort)(crc ^ (value[i]));
                for (int j = 0; j < 8; j++)
                {
                    crc = (crc & 1) != 0 ? (ushort)((crc >> 1) ^ 0xA001) : (ushort)(crc >> 1);
                }
            }
            byte hi = (byte)((crc & 0xFF00) >> 8); // 高位置
            byte lo = (byte)(crc & 0x00FF);       // 低位置

            value[value.Length - 2] = lo;
            value[value.Length - 1] = hi;
        }

        public void Dispose()
        {
            if (!_disposed)
            {
                SafeCloseSerialPort();
                _serialPort?.Dispose();
                _serialLock?.Dispose();
                _disposed = true;
            }
        }
    }
}
